home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
LISP
/
XLISP
/
XLISP21S
/
sources
/
c
/
unixstuf
< prev
next >
Wrap
Text File
|
1992-04-25
|
16KB
|
680 lines
/*I doubt that standard input and output can be redirected with this version*/
/* -*-C-*-
********************************************************************************
*
* File: unixstuff.c
* Description: UNIX-Specific interfaces for XLISP
* Author: David Michael Betz; Niels Mayer
*
* WINTERP 1.0 Copyright 1989 Hewlett-Packard Company (by Niels Mayer).
* XLISP version 2.1, Copyright (c) 1989, by David Betz.
*
* Modified again by Tom Almy
* some SYSV modifications by Dave Rivers (rivers@ponds.uucp)
* some bugs fixed by Hume Smith (850347s@aucs.acadiau.ca)
* yet another fix by Tom Almy
********************************************************************************
*/
/*****************************************************************************
* edit history
*
* 92Jan29 CrT. Edit history. Reversed SysV gtty/stty #defs fixed.
*****************************************************************************/
#include <signal.h>
#include <sys/types.h>
#include <sys/times.h>
#ifdef BSD
#include <sys/ioctl.h>
struct sgttyb savetty;
struct sgttyb newtty;
#define gtty(fd,arg) (ioctl(fd, TIOCGETP, arg))
#define stty(fd,arg) (ioctl(fd, TIOCSETP, arg))
#else
#include <termio.h>
struct termio savetty;
struct termio newtty;
#define gtty(fd,arg) (ioctl(fd, TCGETA, arg))
#define stty(fd,arg) (ioctl(fd, TCSETAF, arg))
#endif
#include "xlisp.h"
#define LBSIZE 200
#ifndef HZ
#define HZ 60
#endif
/* -- external variables */
extern FILEP tfp;
extern long times();
extern LVAL xlenv, xlfenv, xldenv;
/* -- local variables */
static char lbuf[LBSIZE];
static int lpos[LBSIZE];
int lposition; /* export this */
static int lindex;
static int lcount;
char *xfgets();
char read_keybd();
/******************************************************************************
* xsystem - run a process, sending output (if any) to stdout/stderr
*
* syntax: (system <command line>)
* <command line> is a string to be sent to the subshell (sh).
*
* Returns T if the command executed succesfully, otherwise returns the
* integer shell exit status for the command.
*
* Added to XLISP by Niels Mayer
* didn't spawn a shell with null string HCLS
* didn't reset terminal for interaction HCLS
******************************************************************************/
LVAL
xsystem()
{
char * getenv();
extern LVAL true;
char *comstr;
LVAL command;
int result;
char temptext[1024];
/* get shell command */
command = xlgastring();
xllastarg();
comstr = (char *) getstring(command);
if (*comstr) {
/* restore the terminal */
stty(0, &savetty);
/* run the process */
result = system(comstr);
/* restore the terminal */
stty(0, &newtty);
if (result == -1) { /* if a system error has occured */
xlfail("error in system call");
}
} else {
/*
* We were given a null string. We'll try to find out what
* shell the user uses and spawn it.
*/
if (comstr = getenv("SHELL")) {
int pid;
/*
* we could just system(comstr), but that would get
* two shells running...
*/
/* restore the terminal */
stty(0, &savetty);
pid = fork();
if (pid == 0) {
extern int errno;
execl(comstr, comstr, 0);
exit(errno);
}
if (pid == -1) {
xlfail("error in system call");
}
while (pid != wait(&result));
stty(0, &newtty);
result >>= 8;
} else {
/* SHELL is expected (environ(5)) */
xlfail("can't find SHELL variable");
}
}
/*
* return T if success (exit status 0), else return exit status
*/
return (result ? cvfixnum(result) : true);
}
/******************************************************************************/
/* -- Written by dbetz for XLISP 2.0 */
/* -- osinit - initialize */
VOID osinit(banner)
char *banner;
{
fprintf(stderr,"%s\nUNIX version\n", banner );
init_tty();
lindex = 0;
lcount = 0;
}
/* -- osfinish - clean up before returning to the operating system */
VOID osfinish()
{
stty(0, &savetty);
}
/* -- xoserror - print an error message */
VOID xoserror(msg)
char *msg;
{
printf( "error: %s\n", msg );
}
/* osrand - return next random number in sequence */
long osrand(rseed)
long rseed;
{
long k1;
/* make sure we don't get stuck at zero */
if (rseed == 0L) rseed = 1L;
/* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
k1 = rseed / 127773L;
if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
rseed += 2147483647L;
/* return a random number between 0 and MAXFIX */
return rseed;
}
#ifdef FILETABLE
extern VOID gc();
int truename(name, rname)
char *name,*rname;
{
int i;
char *cp;
char pathbuf[FNAMEMAX+1]; /* copy of path part of name */
char curdir[FNAMEMAX+1]; /* current directory */
char *fname; /* pointer to file name part of name */
/* parse any drive specifier */
/* check for absolute path (good news!) */
if (*name == '/') {
strcpy(rname, name);
}
else {
strcpy(pathbuf, name);
if ((cp = strrchr(pathbuf, '/')) != NULL) { /* path present */
cp[1] = 0;
fname = strrchr(name, '/') + 1;
}
else {
pathbuf[0] = 0;
fname = name;
}
/* get the current directory of the selected drive */
getcwd(curdir, FNAMEMAX);
/* peel off "../"s */
while (strncmp(pathbuf, "../", 3) == 0) {
if (*curdir == 0) return FALSE; /* already at root */
strcpy(pathbuf, pathbuf+3);
if ((cp=strrchr(curdir+1, '/')) != NULL)
*cp = 0; /* peel one depth of directories */
else
*curdir = 0; /* peeled back to root */
}
/* allow for a "./" */
if (strncmp(pathbuf, "./", 2) == 0)
strcpy(pathbuf, pathbuf+2);
/* final name is /curdir/pathbuf/fname */
if (strlen(pathbuf)+strlen(curdir)+strlen(fname)+4 > FNAMEMAX)
return FALSE;
if (*curdir)
sprintf(rname, "%s/%s%s", curdir, pathbuf, fname);
else
sprintf(rname, "/%s%s", pathbuf, fname);
}
return TRUE;
}
int getslot()
{
int i=0;
for (; i < FTABSIZE; i++) /* look for available slot */
if (filetab[i].fp == NULL) return i;
gc(); /* is this safe??????? */
for (; i < FTABSIZE; i++) /* try again -- maybe one has been freed */
if (filetab[i].fp == NULL) return i;
xlfail("too many open files");
return 0; /* never returns */
}
FILEP osopen(name, mode)
char *name, *mode;
{
int i=getslot();
char namebuf[FNAMEMAX+1];
FILE *fp;
if (!truename((char *)name, namebuf))
strcpy(namebuf, name); /* should not happen */
if ((filetab[i].tname = (char *)malloc(strlen(namebuf)+1)) == NULL) {
free(filetab[i].tname);
xlfail("insufficient memory");
}
if ((fp = fopen(name,mode)) == NULL) {
free(filetab[i].tname);
return CLOSED;
}
filetab[i].fp = fp;
strcpy(filetab[i].tname, namebuf);
return i;
}
void osclose(f)
FILEP f;
{
fclose(filetab[f].fp);
free(filetab[f].tname);
filetab[f].tname = NULL;
filetab[f].fp = NULL;
}
#endif
#ifdef PATHNAMES
/* ospopen - open using a search path */
FILEP ospopen(name, ascii)
char *name;
int ascii; /* value not used in UNIX */
{
char *getenv();
FILEP fp;
char *path = getenv(PATHNAMES);
char *newnamep;
char ch;
char newname[256];
/* don't do a thing if user specifies explicit path */
if (strchr(name,'/') != NULL || path == NULL)
return OSAOPEN(name, "r");
do {
if (*path == '\0') /* no more paths to check */
/* check current directory just in case */
return OSAOPEN(name, "r");
newnamep = newname;
while ((ch = *path++) != '\0' && ch != ':' && ch != ' ')
*newnamep++ = ch;
if (ch == '\0') path--;
if (*(newnamep-1) != '/')
*newnamep++ = '/'; /* final path separator needed */
*newnamep = '\0';
strcat(newname, name);
fp = OSAOPEN(newname, "r");
} while (fp == CLOSED); /* not yet found */
return fp;
}
#endif
/* rename argument file as backup, return success name */
/* For new systems -- if cannot do it, just return TRUE! */
int renamebackup(filename)
char *filename;
{
char *bufp, ch=0;
strcpy(buf, filename); /* make copy with .bak extension */
bufp = &buf[strlen(buf)]; /* point to terminator */
while (bufp > buf && (ch = *--bufp) != '.' && ch != '/') ;
if (ch == '.') strcpy(bufp, ".bak");
else strcat(buf, ".bak");
unlink(buf);
return !rename(filename, buf);
}
/* -- ostgetc - get a character from the terminal */
int ostgetc()
{
while(--lcount < 0 )
{
if ( xfgets(lbuf,LBSIZE,stdin) == NULL )
return( EOF );
lcount = strlen( lbuf );
if (tfp!=CLOSED) OSWRITE(lbuf,1,lcount,tfp);
lindex = 0;
lposition = 0;
}
return( lbuf[lindex++] );
}
/* -- ostputc - put a character to the terminal */
VOID ostputc( ch )
int ch;
{
char buf[1];
buf[0] = ch;
if (ch == '\n') lposition = 0;
else lposition++;
/* -- output the character */
/* putchar( ch ); */
write(1,buf,1);
/* -- output the char to the transcript file */
if ( tfp != CLOSED )
OSPUTC( ch, tfp );
}
/* -- osflush - flush the terminal input buffer */
VOID osflush()
{
lindex = lcount = lposition = 0;
}
void oscheck()
{
}
osx_check(ch)
char ch;
{
switch (ch) {
case '\003':
xltoplevel(); /* control-c */
case '\007':
xlcleanup(); /* control-g */
case '\020':
xlcontinue(); /* control-p */
case '\024': /* control-t */
xinfo();
printf("\n ");
}
}
/* -- ossymbols - enter os-specific symbols */
VOID ossymbols()
{
}
/* xinfo - show information on control-t */
static xinfo()
{
extern int nfree, gccalls;
extern long total;
char tymebuf[100];
time_t tyme;
char buf[500];
time(&tyme);
strcpy(tymebuf, ctime(&tyme));
tymebuf[19] = '\0';
sprintf(buf,"\n[ %s Free: %d, GC calls: %d, Total: %ld ]",
tymebuf, nfree,gccalls,total);
errputstr(buf);
}
/* xflush - flush the input line buffer and start a new line */
static xflush()
{
osflush();
ostputc('\n');
}
char read_keybd()
{
int nrd;
char buf[2];
nrd = read(0, buf, 1);
buf[nrd] = 0;
if (buf[0] != 127 && buf[0] != 8)
stdputstr(buf);
return(buf[0]);
}
#ifndef BSD
/* SYS V requires reseting of SIGINT */
VOID xlresetint()
{
signal(SIGINT, xlresetint);
xltoplevel();
}
#endif
init_tty()
{
/* extern sigcatch(); */
extern onsusp();
#ifdef BSD
signal(SIGINT, xltoplevel);
#else
signal(SIGINT, xlresetint);
#endif
signal(SIGQUIT, SIG_IGN);
#ifdef SIGTSTP
if (signal(SIGTSTP, onsusp) == SIG_DFL) {
signal(SIGTSTP, onsusp);
}
#endif
if (gtty(0, &savetty) == -1) {
printf("ioctl failed: not a tty\n");
exit();
}
newtty = savetty;
#ifdef BSD
newtty.sg_flags |= CBREAK; /* turn off canonical mode */
/* i.e., turn on cbreak mode */
newtty.sg_flags &= ~ECHO; /* turn off character echo */
#else
newtty.c_lflag &= ~ICANON; /* SYS 5 */
newtty.c_lflag &= ~ECHO;
newtty.c_cc[VMIN] = 1;
newtty.c_cc[VTIME] = 1;
#endif
/*
* You can't request that it try to give you at least
* 5 characters, nor set the timeout to 10 seconds,
* as you can in the S5 example. If characters come
* in fast enough, though, you may get more than one.
*/
if (stty(0, &newtty) == -1) {
printf("cannot put tty into cbreak mode\n");
exit();
}
}
onsusp()
{
#ifdef SIGSTP
/* ignore SIGTTOU so we dont get stopped if csh grabs the tty */
signal(SIGTTOU, SIG_IGN);
stty(0, &savetty);
xflush();
signal(SIGTTOU,SIG_DFL);
/* send the TSTP signal to suspend our process group */
signal(SIGTSTP, SIG_DFL);
sigsetmask(0);
kill(0, SIGTSTP);
/* pause for station break */
/* we re back */
signal(SIGTSTP, onsusp);
stty(0, &newtty);
#endif
}
char *xfgets(s, n, iop)
char *s;
register FILE *iop;
{
register c;
register char *cs;
cs = s;
while (--n>0 && (c = read_keybd()) != EOF) {
switch(c) {
case '\002' : /* CTRL-b */
case '\003' : /* CTRL-c */
case '\007' : /* CTRL-g */
case '\020' : /* CTRL-p */
case '\024' : osx_check(c); /* CTRL-t */
n++;
break;
case 8 :
case 127 : if (cs==s) break; /* not before beginning */
if (c == 127) { /* perform erase */
stdputstr("\010");
stdputstr(" ");
}
stdputstr("\010"); /* BACKSPACE */
n+=2;
cs--;
break;
default : *cs++ = c; /* character */
}
if (c=='\n') break;
}
if (c == EOF && cs==s) return(NULL);
*cs++ = '\0';
return(s);
}
#ifdef TIMES
/***********************************************************************/
/** **/
/** Time and Environment Functions **/
/** **/
/***********************************************************************/
unsigned long ticks_per_second() { return((unsigned long) HZ); }
unsigned long run_tick_count()
{
struct tms tm;
times(&tm);
return((unsigned long) tm.tms_utime + tm.tms_stime );
}
unsigned long real_tick_count()
{ /* Real time */
return((unsigned long) (60 * (time((unsigned long *) NULL))));
}
LVAL xtime()
{
LVAL expr, result;
unsigned long tm, rtm;
double dtm, rdtm;
/* get the expression to evaluate */
expr = xlgetarg();
xllastarg();
tm = run_tick_count();
rtm = real_tick_count();
result = xleval(expr);
tm = run_tick_count() - tm;
rtm = real_tick_count() - rtm;
dtm = (tm > 0) ? tm : -tm;
rdtm = (rtm > 0) ? rtm : -rtm;
sprintf(buf, "CPU %.2f sec., Real %.2f sec.\n", dtm / ticks_per_second(),
rdtm / ticks_per_second());
trcputstr(buf);
return(result);
}
LVAL xruntime() {
xllastarg();
return(cvfixnum((FIXTYPE) run_tick_count()));
}
LVAL xrealtime() {
xllastarg();
return(cvfixnum((FIXTYPE) real_tick_count()));
}
#endif
#ifndef BSD
#if 0
/*
* substitute for BSD/SVR3 rename() system call, from
* Janet Walz, walz@mimsy.umd.edu & Rich Salz, rsalz@pineapple.bbn.com
*/
int
rename(oldname,newname)
char *oldname,*newname;
{
(void)unlink(newname);
if(link(oldname,newname))
return(-1);
return(unlink(oldname));
}
#endif
#endif